/**
* @file gdt.h
* Global Description Table Interface Implementation for X86 architecture.
* Provides the interface for managing GDT over HAL. GDT handles basic
* memory map and mapadding it with descriptors.
*
* Copyrights 2010 Michal Saman, m.saman@designplus.cz
* This source code is release under the Apache License 2.0.
* http://www.apache.org/licenses/LICENSE-2.0
*/

#ifndef _GDT_H
#define _GDT_H

#ifndef ARCH_X86
#error "[gdt.h] is platform-independent. Define ARCH_X86."
#endif

#include <stdint.h>

/** Maximum amout of allowed descriptors */
#define	GDT_MAX_DESCRIPTORS		3

/** GDT descriptor access bit flags. */

/** Descriptor TYPE flags:
 * CODE
 * For code segments, the three low-order bits of the type field are interpreted as
 * accessed (A), read enable (R), and conforming (C). In protected mode, code segments are not writable.
 * DATA
 * For data segments, the three low-order bits of the type field (bits 8, 9, and 10) are
 * interpreted as accessed (A), write-enable (W), and expansion-direction (E).
 */
/** set access bit */
#define GDT_DESC_ACCESS			0x0001		// 00000001
/** Set descriptor readeble and writeble, default: read only */
#define GDT_DESC_READWRITE		0x0002		// 00000010
/** Set expansion direction bit/conforming bit */
#define GDT_DESC_EXP_CONF		0x0004		// 00000100

/** Set executable code segment, default: data segment */
#define GDT_DESC_EXEC_CODE		0x0008		// 00001000
/** Set it is code,data descriptor, default: system defined descriptor. */
#define GDT_DESC_CODEDATA		0x0010		// 00010000
/** Set dpl bits - descriptor protection level (0-3) */
#define GDT_DESC_DPL			0x0060		// 01100000
/** Set "in memory" bit */
#define GDT_DESC_MEMORY			0x0080		// 10000000

/** GDT descriptor grandularity bit flags. */

/** Masks out limitHi (high 4 buts of limit) */
#define GDT_GRAND_LIMITHI_MASK	0x0F		// 00001111
/** AVL - avaiable for use by system software */
#define	GDT_GRAND_OS			0x10		// 00010000
/** set if 64bit segment (IA-32e mode only) */
#define GDT_GRAND_64BIT			0x20		// 00100000
/** set if 32bit, default: 16bit (D/B - Default operation size, 0 = 16bit segment, 1=32bit segment) */
#define GDT_GRAND_32BIT			0x40		// 01000000
/** 4k grandularity switch (Granuality, 0 = 1b, 1 = 4Kb) */
#define GDT_GRAND_4K			0x80		// 10000000

//#pragma pack (push, 1)
/**
* Structure specified properties of a specific memory block.
* GDT table is memory map (array) build from gdtDescriptors.
* The maximum numbers defined in GDT is specified by MAX_DESCRIPTORS.
*/
struct GdtDescriptor {
	uint16_t	limit;			/**< segment size limit, bit 0-15 */
	uint16_t	baseLo;			/**< bit 0-15 of base address */
	uint8_t		baseMid;		/**< bit 16-23 of base address */
	uint8_t		flags;			/**< access flags */
	uint8_t		grand;			/**< granduality flags */
	uint8_t		baseHi;			/**< bit 24-32 of base address */
};
//#pragma pack (pop, 1)

extern struct GdtDescriptor * gdt_get_descriptor(int i);
extern void gdt_set_descritor(uint32_t i, uint64_t base, uint64_t limit, uint8_t access, uint8_t grand);
extern int gdt_init();

#endif
